<?php
// $Id: simple_cart.api.inc,v 1.3 2011/02/16 22:07:08 vladsavitsky Exp $
/*
 * @file
 * simple_cart.api.inc API for Simple Cart module
 */

/**
 * General note:
 * If node has quantity equal to zero or less - this node is removed and shouldn't be shown.
 */

/**
 * ===========================================================================
 * Cart functions
 * ===========================================================================
 */

/**
 * Returns list of nodes in cart.
 *
 * @param string $op Operation. Can be 'simple_list' (default) and 'grouped_by_node_type'.
 * @param string $sid Session ID.
 *        If $sid was not specified - used current user session ID.
 * @return mixed Returns FALSE if cart is empty or array of node's data:
 *        key = nid
 *        value = array(
 *          'nid' => $data['nid'],
 *          'title' => $data['title'],
 *          'quantity'  => $data['quantity'],
 *        );
 */
function simple_cart_get_content($op='simple_list', $sid='') {
  switch ($op) {
    case 'simple_list':
      return simple_cart_get_content_list($sid);
      break;
    case 'grouped_by_node_type':
      $selected_types = _simple_cart_get_selected_types();
      foreach ($selected_types as $type) {
        $cart_content[$type] = simple_cart_get_content_by_type($type, $sid='');
      }
      return $cart_content;
      break;
  }
}

/**
 * Returns current total price of all items in cart.
 *
 * @param string $sid Session ID.
 * @return string Total price amount.
 */
function simple_cart_get_total_price($sid='') {
  $cart_items = simple_cart_get_content_list($sid);
  return $cart_items['total_price'];
}

/**
 * Returns cart content in 'simple_list' format.
 *
 * @param string $sid Session ID.
 *        If $sid was not specified - used current user session ID.
 * @return mixed Returns FALSE if cart is empty or array of node's data:
 *      ['items']
 *        key = nid
 *        value = array(
 *          'nid' => $data['nid'],
 *          'title' => $data['title'],
 *          'quantity' => $data['quantity'],
 *          'price' => $data['price'],
 *        );
 *      ['total_price']
 */
function simple_cart_get_content_list($sid='') {
  $sid = simple_cart_get_sid($sid);
  $sql = "SELECT sc.nid, n.title, sc.quantity
          FROM {%s} sc
            LEFT JOIN {node} n USING (nid)
          WHERE sc.sid='%s'
            AND sc.quantity > 0
            AND n.status = 1";
  $result = db_query($sql, SIMPLE_CART_TABLE_NAME, $sid);
  $nid_list = array();
  // Add default values
  $nid_list['total_price'] = 0;
  $nid_list['items']       = array();
    
  while ($data = db_fetch_array($result)) {
    $node = node_load($data['nid']);
    $price_field = variable_get('simple_cart_price_field_' . $node->type, '');
    $price = $node->$price_field;
    $nid_list['items'][$data['nid']] = array(
      'nid'       => check_plain($data['nid']),
      'title'     => check_plain($data['title']),
      'quantity'  => check_plain($data['quantity']),
      'price'     => check_plain($price[0]['amount']),
    );
    $nid_list['total_price'] += $data['quantity'] * $price[0]['amount'];
  }
  
  $nid_list['total_price'] = check_plain($nid_list['total_price']);
  if (count($nid_list) > 0) {
    return $nid_list;
  }
  else {
    return FALSE;
  }
}

/**
 * Returns cart content in 'grouped_by_node_type' format.
 *
 * @param string $sid Session ID.
 *        If $sid was not specified - used current user session ID.
 * @return mixed Returns FALSE if cart is empty or array of node's data:
 *        key = nid
 *        value = array(
 *          'nid' => $data['nid'],
 *          'title' => $data['title'],
 *          'quantity' => $data['quantity'],
 *          'price' => $data['price'],
 *        );
 */
function simple_cart_get_content_by_type($type, $sid='', $reset=FALSE ) {
  $sid = simple_cart_get_sid($sid);
  $nid_list = array();
  $sql = "SELECT n.type, sc.nid, n.title, sc.quantity
          FROM {%s} sc LEFT JOIN {node} n USING (nid)
          WHERE sc.sid='%s' AND sc.quantity > 0 AND n.status = 1 AND n.type ='%s'
          ORDER BY n.type DESC";
  $result = db_query($sql, SIMPLE_CART_TABLE_NAME, $sid, $type);
  while ($data = db_fetch_array($result)) {
    $node = node_load($data['nid']);
    $price_field = variable_get('simple_cart_price_field_' . $node->type, '');
    $price = $node->$price_field;
    // Amount of items can be zero (gifts) or negative (discounts) so we check if price was set for this node.
    // If price wasn't set we use zero price:
    if ($price[0]['currency'] == NULL && $price[0]['amount'] == NULL) {
      $price[0]['currency'] = 'USD';
      $price[0]['amount'] = '0';
    }
    $nid_list[$data['nid']] = array(
      'nid'       => check_plain($node->nid),
      'title'     => check_plain($data['title']),
      'quantity'  => check_plain($data['quantity']),
      'price'     => check_plain($price[0]['amount']),
    );
  }
  if (count($nid_list) > 0) {
      return $nid_list;
  }
  else {
    return FALSE;
  }
}



/**
 * Adds node to cart.
 * If node already in cart - increase quantity.
 *
 * @param integer $nid Node's ID
 * @param integer $quantity Number of node's copy which should be added to cart.
 * @param string $sid Session ID
 *        If $sid was not specified - used current user session ID.
 * @return integer Return current (resulting) quantity for given node in cart
 */
function simple_cart_add_node($nid, $quantity=0, $sid='') {
  $sid = simple_cart_get_sid($sid);
  $quantity_in_cart = simple_cart_get_node_quantity($nid, $sid);
  if ($quantity_in_cart === FALSE) {
    // Add new node
    if ($quantity > 0) {
      $sql = "INSERT INTO {%s} (sid, nid, quantity) VALUES ('%s', %d, %d)";
      db_query($sql, SIMPLE_CART_TABLE_NAME, check_plain($sid), check_plain($nid), check_plain($quantity));
    }
    else {
      // Do not insert node with negative quantity!
      return FALSE;
    }
  }
  else {
    // Node already in cart
    $quantity = $quantity_in_cart + $quantity;
    if ($quantity > 0) {
      $sql = "UPDATE {%s} SET quantity = %d WHERE sid = '%s' AND nid = %d";
      db_query($sql, SIMPLE_CART_TABLE_NAME, check_plain($quantity), check_plain($sid), check_plain($nid));
    }
    else {
      // Node has negative quantity and should be removed:
      simple_cart_remove_node($nid, $sid);
    }
  }
  return $quantity;
}

/**
 * Returns quantity for given node in cart.
 *
 * @param integer $nid Node ID.
 * @param string $sid Session ID.
 *        If $sid was not specified - used current user session ID.
 * @return integer Number of given node in cart.
 */
function simple_cart_get_node_quantity($nid, $sid='') {
  $sid = simple_cart_get_sid($sid);
  $sql = "SELECT quantity FROM {%s} WHERE sid='%s' AND nid=%d";
  return db_result(db_query($sql, SIMPLE_CART_TABLE_NAME, $sid, $nid));
}

/**
 * Sets given quantity for given node.
 *
 * @param integer $nid Node ID.
 * @param integer $quantity Quantity of nodes.
 *        If positive - nodes will be added to cart.
 *        If negative - this node will be removed.
 * @param string $sid Session ID.
 *        If $sid was not specified - used current user session ID.
 */
function simple_cart_update_node_quantity($nid, $quantity, $sid='') {
  $sid = simple_cart_get_sid($sid);
  if ($quantity > 0) {
    $sql = "UPDATE {%s} SET quantity = %d WHERE sid = '%s' AND nid = %d";
    db_query($sql, SIMPLE_CART_TABLE_NAME, check_plain($quantity), check_plain($sid), check_plain($nid));
  }
  else {
    // Node has negative quantity or equal zero and should be removed:
    simple_cart_remove_node($nid, $sid);
  }
}

/**
 * Removes node with given nid from cart.
 *
 * @param integer $nid Node ID.
 * @param string $sid Session ID.
 *        If $sid was not specified - used current user session ID.
 */
function simple_cart_remove_node($nid, $sid='') {
  $sid = simple_cart_get_sid($sid);
  $sql = "DELETE FROM {%s} WHERE sid='%s' AND nid=%d";
  db_query($sql, SIMPLE_CART_TABLE_NAME, check_plain($sid), check_plain($nid));
}

/**
 * Remove all cart content for given Session ID.
 *
 * @param string $sid Session ID.
 *        If $sid was not specified - used current user session ID.
 */
function simple_cart_empty($sid='') {
  $sid = simple_cart_get_sid($sid);
  $sql = "DELETE FROM {%s} WHERE sid='%s'";
  db_query($sql, SIMPLE_CART_TABLE_NAME, check_plain($sid));
}

/**
 * Returns number of items in cart.
 * Items quantity also respects.
 *
 * @uses simple_cart_get_sid()
 * @uses simple_cart_get_content_list()
 * @param string $sid Session ID.
 *        If $sid was not specified - used current user session ID.
 * @return integer Number of items in cart.
 */
function simple_cart_count_items($sid='') {
  $sid = simple_cart_get_sid($sid);
  $counter = 0;
  $cart_items = simple_cart_get_content_list();
  if (count($cart_items['items'])) {
    foreach ($cart_items['items'] as $item => $item_data) {
      $counter += $item_data['quantity'];
    }
  }
  return check_plain($counter);
}

/**
 * ===========================================================================
 * Session functions
 * ===========================================================================
 */

/**
 * Returns session ID for current user if $sid is empty
 *
 * @param string $sid Session ID
 * @return string Returns session ID
 */
function simple_cart_get_sid($sid='') {
  if (!$sid) {
    return $_COOKIE[session_name()];
  }
  else {
    return $sid;
  }
}


/**
 * ===========================================================================
 * Content types functions
 * ===========================================================================
 */

/**
 * Check if node type is allowed to be added to cart
 *
 * @param string $type Content type
 * @return boolean Returns TRUE if given node type can be added to cart
 */
function simple_cart_is_type_cartable($type) {
  return (boolean)variable_get('simple_cart_is_cartable_' . $type, '');
}

/**
 * Returns an array of content types allowed to work with cart.
 *
 * @return array
 */
function simple_cart_get_cartable_types() {
  $node_types = node_get_types('names');
  foreach ($node_types as $type => $name) {
    if (variable_get('simple_cart_is_cartable_' . $type, '')) {
      $cartable_types[] = $type;
    }
  }
  return $cartable_types;
}

/**
 * @TODO: create function to add content type to 'selected'
 * Rename selected to use products
 * Use selected field name instead of price
 */
